Skip to content

Conversation

wassertim
Copy link
Owner

Summary

Fixes #4 - Mapper generation now correctly handles List<Integer>, List<Double>, and other primitive wrapper lists.

Problem

The annotation processor was failing to generate valid mapper code when encountering List<Integer> fields, attempting to use a non-existent ListMapper class and causing compilation errors.

Root Cause

The TypeAnalyzer lacked a mapping strategy for lists of primitive wrapper types. It only handled:

  • List<String> → STRING_LIST
  • List<List<Number>> → NESTED_NUMBER_LIST
  • List<@DynamoMappable> → COMPLEX_LIST

Lists of primitive wrappers fell through to COMPLEX_OBJECT, which incorrectly tried to generate mapper dependencies.

Solution

Core Changes

  1. Added NUMBER_LIST mapping strategy (FieldInfo.java)

    • New enum value for handling lists of numeric types
  2. Enhanced type detection (TypeAnalyzer.java)

    • Now detects numeric element types in lists and maps them to NUMBER_LIST strategy
    • Checks both wrapper types (Integer, Double, etc.) and primitives
  3. Implemented code generation (FieldMappingCodeGenerator.java)

    • Serialization: Converts List<Integer> to DynamoDB list format (L) with number attributes (N)
    • Deserialization: Converts DynamoDB lists back to typed lists using appropriate numeric methods

Test Coverage

Added comprehensive integration tests (ListIntegerMappingTest.java):

  • ✅ Basic List field mapping
  • ✅ Round-trip conversion (serialize → deserialize)
  • ✅ Null list handling
  • ✅ Empty list handling

Generated Code Example

Before (compilation error):

private final ListMapper listMapper;  // ❌ ListMapper doesn't exist

After (working):

// Serialization
if (obj.getWaypointIndices() != null) {
    List<AttributeValue> list = obj.getWaypointIndices().stream()
        .map(val -> AttributeValue.builder().n(String.valueOf(val)).build())
        .collect(Collectors.toList());
    attributes.put("waypointIndices", AttributeValue.builder().l(list).build());
}

// Deserialization
List<AttributeValue> listValue = MappingUtils.getListSafely(attr);
if (listValue != null) {
    List<Integer> result = listValue.stream()
        .map(MappingUtils::getIntegerSafely)
        .filter(Objects::nonNull)
        .collect(Collectors.toList());
    builder.waypointIndices(result);
}

Test Results

All 27 integration tests pass, including 4 new tests for List mapping.

Resolves #4

The annotation processor now correctly handles List<Integer>, List<Double>,
and other primitive wrapper lists by generating proper DynamoDB list mapping
code instead of attempting to use a non-existent ListMapper.

Changes:
- Added NUMBER_LIST mapping strategy to FieldInfo.MappingStrategy enum
- Updated TypeAnalyzer to detect numeric element types in lists
- Implemented serialization and deserialization code generation for NUMBER_LIST
- Added comprehensive tests for List<Integer> mapping

The generated mappers now directly convert primitive wrapper lists to
DynamoDB's native list format (L) with number attributes (N).
- Added NUMBER_LIST mapping strategy to FieldInfo.MappingStrategy enum
- Updated TypeAnalyzer to detect numeric element types in lists
- Implemented serialization and deserialization in FieldMappingCodeGenerator
@wassertim wassertim merged commit fefb30f into main Oct 4, 2025
2 checks passed
@wassertim wassertim deleted the fix/list-integer-mapping branch October 4, 2025 11:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Bug: Mapper Generation Fails for List<Integer> Fields
1 participant